from datetime import datetime, timedelta, date
import time
from threading import Condition
from typing import Type
from django import http
from django.forms import models
from django.http import HttpResponseRedirect, request
from django.shortcuts import get_object_or_404, redirect, render
from django.http import HttpResponse
from django.views.generic import View
from hosSystem import models
from django.utils import timezone
from django.db import transaction
from django.contrib import messages
from inpatient.models import InPatient


def func():
    """
    服务启动时清理数据库
    """
    # 1.清理patient_line数据库
    q_set = models.PatientLine.objects.filter(work_time__lt=date.today())
    for q in q_set:
        q.delete()
    # 2.清理医生工作表的过期医生排班数据
    q_set = models.DoctorsWork.objects.filter(work_time__lt=date.today())
    for q in q_set:
        q.delete()


func()
# Create your views here.


class login(View):
    """
    @description  :用户的登录页面
    """

    def get(self, request, *args, **kwargs):
        return render(request, 'signin.html')

    def post(self, request, *args, **kwargs):
        p_id = request.POST.get('id')
        p_name = request.POST.get('name')
        try:
            patient = get_object_or_404(models.Patients, id_patient=p_id)
            if patient.id_patient == p_id and patient.name_patient == p_name:
                p_contact = patient.contact_patient
                context = {'id': p_id, 'name': p_name, 'contact': p_contact}
                request.session['msg1'] = context
                return redirect('/hosSystem/operation')
            else:
                raise ValueError
        except Exception as er:  # 未能成功匹配或数据库中不存在该用户
            self.alert(request=request)
            return redirect('/hosSystem/signin')

    def alert(self, request):
        messages.warning(request, '登陆失败！错误的用户名密码或未注册！')


class logup(View):
    """
    @description  :用户的注册页面
    """

    def get(self, request, *args, **kwargs):
        return render(request, 'signup.html')

    def post(self, request, *args, **kwargs):  # 获取用户输入信息->判断->存入数据库
        systemDict = {}
        for key in request.POST:
            if key == 'id' or key == 'name' or key == 'contact':
                systemDict[key] = request.POST.get(key)
            elif key == 'sex' or key == 'age':
                if request.POST.get(key) != '':
                    systemDict[key] = int(request.POST.get(key))
                else:
                    systemDict[key] = request.POST.get(key)
        A = models.Patients()
        try:
            patient = get_object_or_404(
                models.Patients, id_patient=systemDict['id'])
            self.alert(request=request, text='您已经注册过！将为您跳转至登陆页面!')
        except:
            A.id_patient = systemDict['id']
            A.name_patient = systemDict['name']
            A.sex_patient = systemDict['sex']
            A.age_patient = systemDict['age']
            A.contact_patient = systemDict['contact']
            A.save()
            self.alert(request=request, text='注册成功！将为您跳转至登录界面!')
        finally:
            return redirect('/hosSystem/signin')

    def alert(self, request, text):
        messages.warning(request, text)


class operation(View):
    """
    @description :用户的操作界面的类视图
    需要修改让session成为公有属性
    """

    def get(self, request, *args, **kwargs):
        try:
            context = request.session.get('msg1')
            request.session['msg2'] = context
            # request.session['msg1']=None   #清理session
            if context is None:
                raise ValueError
            else:
                return render(request, 'operate.html', context=context)
        except ValueError as ve:
            return render(request, 'warnSign.html')  # 用404.html
        # sessions需要被清理 用户在注销后系统需清理session

    def post(self, request, *args, **kwargs):
        # request.session['msg']=context  #将病人的信息传入session以在下一个视图中操作 此处为NONE bug
        if request.POST.get('查看病例') == '查看病例':
            return redirect('/hosSystem/operation/case')
        if request.POST.get('挂号') == '挂号':
            return redirect('/hosSystem/operation/registration')
        if request.POST.get('查看状态') == '查看状态':
            return redirect('/hosSystem/operation/status')


class case(View):
    def get(self, request, *args, **kwargs):
        context = request.session.get('msg1')
        C = models.Case.objects.filter(patient_id=context['id'])
        clist = []
        for c in C:
            alist = []
            alist.append(c.text)
            alist.append(c.name_doctor)
            alist.append(c.type_doctor)
            alist.append(c.diagnoseTime)
            clist.append(alist)
        clist.sort(key=lambda x: x[-1], reverse=True)
        context = {'caselist': clist}
        return render(request, 'check_case.html', context=context)


class check_status(View):
    def get(self, request, *args, **kwagrs):
        context = request.session.get('msg1')
        P = models.PatientLine.objects.filter(id_patient_id=context['id'])
        infotext = {}
        infotext['name'] = context['name']
        infotext['id'] = context['id']
        infotext['contact'] = context['contact']
        alist = []
        for p in P:
            dlist = []
            # dlist.append(p.id_doctor_id)
            d = models.Doctors.objects.get(id_doctor=p.id_doctor_id)
            dlist.append(d.name_doctor)
            dlist.append(d.workplace_doctor)
            dlist.append(d.consulting_room)
            dlist.append(p.work_time)
            dlist.append('上午' if p.time_quantum == 'AM' else '下午')
            alist.append(dlist)
        alist.sort(key=lambda x: x[-2])
        infotext['doctor'] = alist
        if (len(alist[0]) == 0):
            infotext['status'] = ' 无挂号'
        else:
            infotext['status'] = ' 有挂号'
        return render(request, 'check_status.html', context=infotext)


class registration(View):
    """
    @description  :处理挂号
    """

    def get(self, request, *args, **kwargs):
        try:
            context = request.session.get('msg2')
            request.session['msg3'] = context
            # request.session['msg2']=None  #清理session
            if context is None:
                raise ValueError
            return render(request, 'registration.html', context=context)
        except ValueError as ve:
            return render(request, 'warnSign.html')  # 用404.html

    def post(self, request, *args, **kwargs):
        room = request.POST.get('科室')
        context = request.session.get('msg3')
        context['room'] = room
        request.session['msg3'] = context
        return redirect('/hosSystem/operation/registration/time')


class registime(View):
    """
    @description  :挂号时间 
    """

    def get(self, request, *args, **kwargs):
        try:
            context = request.session.get('msg3')
            request.session['msg4'] = context  # 传输给POST使用
            if context is None:
                raise ValueError
        except ValueError as ve:
            return render(request, 'warnSign.html')
        else:
            t1 = timezone.now()
            t2 = (t1+timezone.timedelta(days=0)).strftime('%Y-%m-%d')
            t3 = (t1+timezone.timedelta(days=1)).strftime('%Y-%m-%d')
            t4 = (t1+timezone.timedelta(days=2)).strftime('%Y-%m-%d')
            t5 = (t1+timezone.timedelta(days=3)).strftime('%Y-%m-%d')
            t6 = (t1+timezone.timedelta(days=4)).strftime('%Y-%m-%d')
            t7 = (t1+timezone.timedelta(days=5)).strftime('%Y-%m-%d')
            t8 = (t1+timezone.timedelta(days=6)).strftime('%Y-%m-%d')
            if 't1' not in list(context.keys()):
                context['t1'] = None
            context['t2'] = t2
            context['t3'] = t3
            context['t4'] = t4
            context['t5'] = t5
            context['t6'] = t6
            context['t7'] = t7
            context['t8'] = t8  # 此时session也得到修改
        if context['t1'] is None:
            date_selected = context['t2']  # 当前选择的时间 年月日
            room = context['room']
            infolist = self.get_context(
                date_selected=date_selected, room=room)  # 用于存放挂号医生信息的列表
            context['infolist'] = infolist
        else:

            flag = context['t1']
            date_selected = context[self.getTime(flag)]  # 当前选择的时间 年月日
            room = context['room']
            infolist = self.get_context(
                date_selected=date_selected, room=room)  # 用于存放挂号医生信息的列表
            context['infolist'] = infolist
        return render(request, 'registration-time.html', context=context)

    def get_context(self, date_selected, room):  # 返回符合病人挂号要求的所有医生的信息
        infolist = []
        A = models.Doctors.objects.filter(consulting_room=room)
        for i in A:
            B = models.DoctorsWork.objects.filter(id_doctor=i.id_doctor)
            for j in B:
                if j.work_time.strftime('%Y-%m-%d') == date_selected:
                    alist = []
                    alist.append(i.name_doctor)
                    if j.level == 'expert':
                        alist.append('专家')
                    else:
                        alist.append('普通')
                    alist.append(j.time_quantum)
                    alist.append(j.num_remain)
                    alist.append(i.id_doctor)
                    alist.append(date_selected)
                    infolist.append(alist)
        return infolist

    def getTime(self, x):
        if x == '1':
            return 't2'
        elif x == '2':
            return 't3'
        elif x == '3':
            return 't4'
        elif x == '4':
            return 't5'
        elif x == '5':
            return 't6'
        elif x == '6':
            return 't7'
        elif x == '7':
            return 't8'

    def post(self, request, *args, **kwargs):
        context = request.session.get('msg4')
        context['t1'] = request.POST.get('date')
        request.session['msg3'] = context  # 传到重定向后的视图get函数中
        # 对挂号请求做处理
        # 需要医生id work_time time_quantum
        info = request.POST.get('挂号')
        if info is not None:
            info = info.split(' ')
            date_time = date(*map(int, info[2].split('-')))
            condition = {
                'id_doctor': info[0], 'time_quantum': info[1], 'work_time': date_time}
            # 通过事务锁修改数据
            with transaction.atomic():
                db = models.DoctorsWork.objects.select_for_update().filter(**condition).first()
                try:
                    if db.num_remain < 1:
                        raise ValueError
                    else:
                        try:  # 挂号队列中已有信息则不做任何操作
                            condition_line = condition
                            # 挂号队列信息主键信息
                            condition_line['id_patient'] = context['id']
                            get_object_or_404(
                                models.PatientLine, **condition_line)
                            self.alert(request=request, msg='请勿重复挂号！')
                        except Exception as er:  # 若还没挂过号则将挂号信息添加到挂号队列 并修改医生的剩余号数
                            db.num_remain = db.num_remain-1
                            db.save()
                            """
                            将该病人的信息导入到医生挂号数据库
                            所需信息: 医生ID 姓名 病人ID 姓名 所挂号日期 挂号时间段（上下午）
                            """
                            A = models.PatientLine()
                            id_doc = condition['id_doctor']
                            name_doc = models.Doctors.objects.all().get(id_doctor=id_doc).name_doctor
                            time_quantum = condition['time_quantum']
                            work_time = condition['work_time']
                            id_patient = context['id']
                            name_patient = context['name']
                            A.id_doctor = models.Doctors.objects.all().get(id_doctor=id_doc)
                            A.name_doctor = name_doc
                            A.id_patient = models.Patients.objects.all().get(id_patient=id_patient)
                            A.name_patient = name_patient
                            A.time_quantum = time_quantum
                            A.work_time = work_time
                            A.save()
                            self.alert(request=request, msg="挂号成功！")
                except ValueError as ve:
                    # 号数不够 网页提醒
                    self.alert(request=request, msg="挂号失败！剩余号数不足！")
        return redirect('/hosSystem/operation/registration/timeS')

    def alert(self, request, msg):
        messages.warning(request, msg)


class docSignin(View):
    """
    @description  :医生的登录页面
    """

    def get(self, request, *args, **kwargs):
        return render(request, 'doctor_signin.html')

    def post(self, request, *args, **kwargs):
        d_id = request.POST.get('id')
        d_pwd = request.POST.get('pwd')
        """
        需增加对医生类型的判断以返回不同的医生对应的操作页面
        """
        try:
            doctor = get_object_or_404(models.Doctors, id_doctor=d_id)
            if doctor.id_doctor == d_id and doctor.pwd_doctor == d_pwd:
                context = {'id': d_id, 'name': doctor.name_doctor,
                           'room': doctor.consulting_room}  # 医生工号 姓名 所在诊室
                request.session['dmsg1'] = context
                if doctor.type_doctor == 'department':
                    return redirect('/hosSystem/doctor/operate')
                elif doctor.type_doctor == 'assay':
                    return redirect('/hosSystem/doctor/assay')
            else:
                raise ValueError
        except Exception as er:  # 未能成功匹配或数据库中不存在该用户
            self.alert(request=request)
            return redirect('/hosSystem/doctor')

    def alert(self, request):
        messages.warning(request, '登陆失败！错误的用户名密码或未注册！')


class docOperate(View):
    """
    @description  :医生操作视图编写
    ---------
    @param  :
    """

    def get(self, request, *args, **kwargs):
        try:
            context = request.session.get('dmsg1')  # 医生工号id 姓名name 所在诊室room
            if context is None:
                raise ValueError
            if 'pinfo' not in list(context.keys()):
                context['pinfo'] = None
            if 'case' not in list(context.keys()):
                context['case'] = None
        except ValueError as ve:
            return redirect('/hosSystem/doctor')
        else:
            # context中新增两个键值对（pNameId:侧边栏的病人姓名和ID  ; pinfo:中间栏的病人信息  )
            condition = {'work_time': date.today(
            ), 'id_doctor': context['id'], 'time_quantum': self.judge_quantum()}
            A = models.PatientLine.objects.filter(**condition)
            pNameId = []
            pinfo = []
            case_list = []
            for index, item in enumerate(A):
                alist = []  # 临时表-存放病人name和id
                alist.append(item.name_patient)
                alist.append(item.id_patient_id)
                pNameId.append(alist)
                if index == 0:
                    p_id = item.id_patient_id
                    pinfo = self.get_Pinfo(id=p_id)
                    case_list = self.get_caselist(
                        id_p=p_id)
            context['pNameId'] = pNameId
            if context['pinfo'] is None:
                context['pinfo'] = pinfo  # pinfo是当前挂号队列里最先挂号的患者
            if context['case'] is None:
                context['case'] = case_list
            request.session['dmsg1'] = context
            # 医生工号id 姓名name 所在诊室room pNameId:侧边栏的病人姓名和ID  ; pinfo:中间栏的病人信息
            return render(request, 'doctor_operate.html', context=context)

    def get_caselist(self, id_p):
        """
        获取病人病例
        """
        case_list = []
        B = models.Case.objects.filter(patient=id_p)
        for i in B:
            blist = []
            blist.append(i.text)
            blist.append(i.name_doctor)
            blist.append(i.type_doctor)
            blist.append(i.diagnoseTime.strftime('%Y-%m-%d %H:%M:%S'))
            case_list.append(blist)
        case_list = sorted(case_list, key=lambda x: x[-1], reverse=True)
        return case_list

    def judge_quantum(self):
        """
        @description  :判断当前时间是上午还是下午
        ---------
        @param  :None
        -------
        @Returns  :PM AM-str
        -------
        """
        hour_now = time.localtime().tm_hour
        if 0 <= hour_now <= 12:
            return 'AM'
        else:
            return 'PM'

    def post(self, request, *args, **kwargs):
        """
        @description  :更换病人 化验 住院 增添病例 治疗 
        取药（待做）
        待生成一个按钮用于解除病人的挂号信息
        ---------
        """
        context = request.session.get(
            'dmsg1')  # 医生工号id 姓名name 所在诊室room pNameId:侧边栏的病人姓名和ID  ; pinfo:中间栏的病人信息
        if request.POST.get('选择病人') is not None:
            if request.POST.get('选择病人').split()[0] == '选择病人':
                p_id = request.POST.get('选择病人').split()[1]
                context['pinfo'] = self.get_Pinfo(id=p_id)  # 更新当前页病人的信息
                case_list = self.get_caselist(id_p=p_id)
                context['case'] = case_list
                request.session['dmsg1'] = context
                return redirect('/hosSystem/doctor/operate')
        if context['pinfo'] is None or len(context['pinfo']) == 0:
            self.alert(request=request, text='当前无病人 无效操作！')
            return redirect('/hosSystem/doctor/operate')
        if request.POST.get('选择化验') is not None:  # 点击了化验按钮
            choice = request.POST.get('account')
            remark = request.POST.get('化验备注信息')
            P = models.Patients.objects.all().get(
                id_patient=context['pinfo'][0])
            if choice == '验血':
                try:
                    A = models.AssayLine()
                    get_object_or_404(models.AssayLine, id_patient=P)
                    self.alert(request=request, text='请勿重复添加！')
                except:
                    A.id_patient = P
                    A.remark = remark
                    A.save()
                    self.alert(request=request, text='添加成功！')
            elif choice == '核磁共振':
                try:
                    A = models.MriLine()
                    get_object_or_404(models.MriLine, id_patient=P)
                    self.alert(request=request, text='请勿重复添加！')
                except:
                    A.id_patient = P
                    A.remark = remark
                    A.save()
                    self.alert(request=request, text='添加成功！')
            elif choice == 'X光':
                try:
                    A = models.XRayLine()
                    get_object_or_404(models.XRayLine, id_patient=P)
                    self.alert(request=request, text='请勿重复添加！')
                except:
                    A.id_patient = P
                    A.remark = remark
                    A.save()
                    self.alert(request=request, text='添加成功！')
        if request.POST.get('选择住院') == '是':
            choice = request.POST.get('住院')  # 是代表确认住院
            remark = request.POST.get('住院备注信息')
            surgery = request.POST.get('手术')  # 是 否
            P = models.Patients.objects.all().get(
                id_patient=context['pinfo'][0])
            if choice == '是':
                try:
                    get_object_or_404(InPatient, id_inpatient=P.id_patient)
                    self.alert(request=request, text='请勿重复添加！')
                except:
                    D = models.Doctors.objects.all().get(
                        id_doctor=context['id'])
                    A = InPatient()
                    A.id_inpatient = P.id_patient
                    A.name_inpatient1 = P.name_patient
                    A.age_inpatient = P.age_patient
                    A.sex_inpatient = P.sex_patient
                    A.contact_inpatient = P.contact_patient
                    A.workplace_doctor = D.workplace_doctor
                    A.save()
                    self.alert(request=request, text='添加成功')
        if request.POST.get('增添病例') == '是':
            A = models.Case()
            P = models.Patients.objects.all().get(
                id_patient=context['pinfo'][0])
            D = models.Doctors.objects.all().get(id_doctor=context['id'])
            case_text = request.POST.get('病例信息')
            A.patient = P
            A.doctors = D
            A.text = case_text
            A.name_doctor = D.name_doctor
            A.name_patient = P.name_patient
            A.type_doctor = D.type_doctor
            A.Surgery = '非手术'
            try:
                get_object_or_404(InPatient, id_inpatient=context['pinfo'][0])
                A.InP = '住院'
            except:
                A.InP = '非住院'
            A.save()
            self.alert(request=request, text='病例添加成功')
        if request.POST.get('诊断完成') == '诊断完成':
            C = models.PatientLine.objects.filter(
                id_patient_id=context['pinfo'][0], id_doctor_id=context['id'])
            context['pinfo'] = None
            context['case'] = None
            request.session['dmsg1'] = context
            for i in C:
                i.delete()
        return redirect('/hosSystem/doctor/operate')

    def alert(self, request, text):
        messages.warning(request, text)

    def get_Pinfo(self, id):
        """
        @description  :传入病人的id获取病人的信息列表
        ---------
        @param  :id
        -------
        @Returns  :pinfo 病人的信息列表 id name sex age contact
        -------
        """
        P = models.Patients.objects.all().get(id_patient=id)
        pinfo = []
        pinfo.append(P.id_patient)
        pinfo.append(P.name_patient)
        pinfo.append('男' if P.sex_patient == 0 else '女')
        pinfo.append(P.age_patient)
        pinfo.append(P.contact_patient)
        return pinfo


class assayOperate(View):
    def get(self, request, *args, **kwargs):
        try:
            context = request.session.get('dmsg1')  # 医生工号id 姓名name 所在诊室room
            if context is None:
                raise ValueError
            if 'pNameId' not in list(context.keys()):
                context['pNameId'] = None
            if 'pinfo' not in list(context.keys()):
                context['pinfo'] = None
        except ValueError as ve:
            return redirect('/hosSystem/doctor')
        else:
            # context中增加两个键值对 1-所有等待化验的病人列表 pNameId 2-当前正在化验的病人pinfo
            pNameId = self.get_pNameId(context=context)
            pinfo = []
            context['pNameId'] = pNameId
            if context['pinfo'] is None:
                context['pinfo'] = pinfo
            request.session['dmsg1'] = context
        return render(request, 'assay_doctor_operate.html', context=context)

    def post(self, request, *args, **kwargs):
        context = request.session.get('dmsg1')

        if request.POST.get('选择病人') is not None:
            id_P = request.POST.get('选择病人')
            P = models.Patients.objects.all().get(id_patient=id_P)
            context['pinfo'] = []
            context['pinfo'].append(P.name_patient)
            context['pinfo'].append('男' if P.sex_patient == 0 else '女')
            context['pinfo'].append(P.age_patient)
            context['pinfo'].append(P.contact_patient)
            context['pinfo'].append(id_P)
            # 化验备注
            if context['room'] == '验血':
                remark = models.AssayLine.objects.all().get(id_patient=id_P).remark
            elif context['room'] == 'X光':
                remark = models.XRayLine.objects.all().get(id_patient=id_P).remark
            elif context['room'] == '核磁共振':
                remark = models.MriLine.objects.all().get(id_patient=id_P).remark
            context['pinfo'].append(remark if remark is not None else '无')
            request.session['dmsg1'] = context
            return redirect('/hosSystem/doctor/assay')

        if context['pinfo'] == []:
            self.alert(request=request, text='请选择当前化验病人再进行操作')
            return redirect('/hosSystem/doctor/assay')

        if request.POST.get('化验完成') == '化验完成':
            # 写入病例 且 将患者移除队列
            id_P = context['pinfo'][-2]
            A = models.Case()
            P = models.Patients.objects.all().get(
                id_patient=id_P)
            D = models.Doctors.objects.all().get(id_doctor=context['id'])
            case_text = request.POST.get('化验结果')
            A.patient = P
            A.doctors = D
            A.text = case_text
            A.name_doctor = D.name_doctor
            A.name_patient = P.name_patient
            A.type_doctor = D.type_doctor
            A.Surgery = '非手术'
            try:
                get_object_or_404(InPatient, id_inpatient=id_P)
                A.InP = '住院'
            except:
                A.InP = '非住院'
            A.save()
            if context['room'] == '验血':
                models.AssayLine.objects.all().get(id_patient=id_P).delete()
            elif context['room'] == 'X光':
                models.XRayLine.objects.all().get(id_patient=id_P).delete()
            elif context['room'] == '核磁共振':
                models.MriLine.objects.all().get(id_patient=id_P).delete()
            context['pinfo'] = []
            request.session['dmsg1'] = context
            self.alert(request=request, text='化验完成！')
            return redirect('/hosSystem/doctor/assay')

    def get_pNameId(self, context):
        """
        根据所给的医生信息返回该医生对应的化验病人信息列表 id name 实例
        """
        if context['room'] == '验血':
            A = models.AssayLine.objects.all()
        elif context['room'] == 'X光':
            A = models.XRayLine.objects.all()
        elif context['room'] == '核磁共振':
            A = models.MriLine.objects.all()
        pNameId = []
        for i in A:
            P = i.id_patient  # 病人对象
            alist = []
            alist.append(P.id_patient)
            alist.append(P.name_patient)
            pNameId.append(alist)
        return pNameId

    def alert(self, request, text):
        messages.warning(request, text)
